package com.lang.throwable;


import org.junit.Test;

/**
 * Exception和Error的父类
 * 用来记录堆栈信息
 */
public class ThrowableDemo {
    /**
     *
     */
    @Test
    public void testPrintStackTrace() {
    }

    /**
     * cause 以链式的形式将栈串联起来
     *  HighLevelException: MidLevelException: LowLevelException
     *          at Junk.a(Junk.java:13)
     *          at Junk.main(Junk.java:4)
     *  Caused by: MidLevelException: LowLevelException
     *          at Junk.c(Junk.java:23)
     *          at Junk.b(Junk.java:17)
     *          at Junk.a(Junk.java:11)
     *          ... 1 more
     *  Caused by: LowLevelException
     *          at Junk.e(Junk.java:30)
     *          at Junk.d(Junk.java:27)
     *          at Junk.c(Junk.java:21)
     *          ... 3 more
         *   这里的 ... 1 more 和 ... 3 more分别代表的是这个异常的堆栈信息下面，还有n个栈帧
         *   1的话 这个一场的堆栈信息 为 c  b  a  然后a下面就只有main一个方法了，所以是1
         *   同理 3 代表 c下面还有3个栈帧
     */
    @Test
    public void testCause() {
        try {
            Junk.a();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 测试 catch Exception 能否捕获Error
     */
//    @Test
//    public void test03(){
    public static void main(String[] args) {
        try {
           test03_1();
        }catch (Exception e){
            e.printStackTrace();
        }
        catch (Error e){
            e.printStackTrace();
        }catch (Throwable e){
            e.printStackTrace();
        }
        System.out.println("aaa");
    }
    private static void test03_1() {
        throw new Error("aa");
    }


    /**
     * 关于 Throwable里面的 synchronized 语法的使用 ???
     * 目测是因为多个地方互相引用的原因
     */


    /**
     * 了解下几个 native 方法，可以了解下虚拟机
     */

}






class Junk {
    public static void main(String args[]) {
        try {
            a();
        } catch(HighLevelException e) {
            e.printStackTrace();
        }
    }

    static void tt() throws HighLevelException {
        try {
            a();
        } catch(HighLevelException e) {
            throw new HighLevelException(e);
        }
    }

    static void a() throws HighLevelException {
        try {
            b();
        } catch(MidLevelException e) {
            throw new HighLevelException(e);
        }
    }
    static void b() throws MidLevelException {
        c();
    }
    static void c() throws MidLevelException {
        try {
            d();
        } catch(LowLevelException e) {
            throw new MidLevelException(e);
        }
    }
    static void d() throws LowLevelException {
        e();

    }
    static void e() throws LowLevelException {
        throw new LowLevelException();
    }
}

class HighLevelException extends Exception {
    HighLevelException(Throwable cause) { super(cause); }
}

class MidLevelException extends Exception {
    MidLevelException(Throwable cause)  { super(cause); }
}

class LowLevelException extends Exception {
}